<?php
/**
 * Created by PhpStorm.
 * User: Administratorjing
 * Date: 2018/4/25/025
 * Time: 23:02
 */

namespace app\api\service;


use app\api\model\OrderProduct;
use app\api\model\Product;
use app\api\model\UserAddress;
use app\lib\enum\OrderStatusEnum;
use app\lib\exception\OrderException;
use app\lib\exception\UserException;
use think\Db;
use think\Exception;
use app\api\model\Order as OrderModel;

class Order
{
   //编写业务逻辑
    //订单的商品列表，从客户端传递过来的参数
    protected $oProducts;
    //真实的商品库存以及信息
    protected $products;

    protected $uid;


    public function place($uid,$oProducts)
    {
       //oProducts 与 products进行比较
        $this->oProducts = $oProducts;
        //products从数据库中查询出来
        $this->products = $this->getProductsByOrder($oProducts);
        $this->uid = $uid;
        $status = $this->getOrderStatus();//status 信息
        if(!$status['pass']){
            $status['order_id'] = -1;
            //返回客户端
            return $status;
        }
        //开始创建订单
        $orderSnap = $this->snapOrder($status);
        $order = $this->createOrder($orderSnap);
        $order['pass'] = true;
        return $order;

    }
    //创建生成订单
    private function createOrder($snap){
        //事务的应用
        Db::startTrans();
        try{
            //生成订单号
            $orderNo = $this->makeOrderNo();
            //实例化模型
            $order = new \app\api\model\Order();
            //填充数据
            $order->user_id = $this->uid;
            $order->order_no = $orderNo;
            $order->total_price = $snap['orderPrice'];
            $order->total_count = $snap['totalCount'];
            $order->snap_img = $snap['snapImg'];
            $order->snap_name = $snap['snapName'];
            $order->snap_address = $snap['snapAddress'];
            $order->snap_items = json_encode($snap['pStatus']);
            //写入数据库
            $order->save();
            //获取数据，从模型中提出
            $orderID = $order->id;
            $create_time = $order->create_time;
            //获取数组下面的每个子项
            foreach ($this->oProducts as &$p)
            {
                $p['order_id'] = $orderID;
            }
            //实例化orderProduct模型
            $orderProduct = new OrderProduct();
            //保存一组数据
            $orderProduct->saveAll($this->oProducts);
            //返回的数据
            //事务的应用
            Db::commit();
            return [
                'order_no'  => $orderNo,
                'order_id'  => $orderID,
                'create_time' => $create_time
            ];
        }catch (Exception $ex){
            //数据库回滚
            Db::rollback();
            throw $ex;
        }
    }

    /**
     * 生成订单号
     * @return string
     */
    public static function makeOrderNo()
    {
        //时间的生成，减少订单的重复性
        $yCode = array('A','B','C','D','E','F','G','H','I','J');
        $orderSn = $yCode[intval(date('Y')) - 2018].strtoupper(dechex(date('m'))).date('d').substr(time(),-5).substr(microtime(),2,5).sprintf('%02d',rand(0.99));
        return $orderSn;
    }

    //生成订单快照
    private function snapOrder($status)
    {
        //相关属性的定义
        $snap = [
            'orderPrice' =>0,
            'totalCount' =>0,
            'pStatus' => [],//商品的状态
            'snapAddress' => null,
            'snapName' =>'',
            'snapImg' =>''
        ];
        $snap['orderPrice'] = $status['orderPrice'];
        $snap['orderCount'] = $status['totalCount'];
        $snap['pStatus'] = $status['pStatusArray'];
        //获取地址,将数组序列化
        $snap['snapAddress'] = json_encode($this->getUserAddress());
        $snap['snapName'] = $this->products[0]['name'];
        $snap['snapImg'] = $this->products[0]['main_img_url'];

        if(count($this->products)>1){
            $snap['snapName'] = '等';
        }
    }

    /**
     * 库存量检测
     * @param $orderID
     */
    public function checkOrderStock($orderID)
    {
        $oProducts = OrderProduct::where('order_id','=',$orderID)->select();
        $this->oProducts = $oProducts;
        $this->products = $this->getProductsByOrder($oProducts);
        $status = $this->getOrderStatus();
        return $status;
    }

    /**
     * 查询用户地址
     * @return array
     * @throws UserException
     */
    private function getUserAddress()
    {
        //外键连接，所以要有user_id,并且等于uid
        $userAddress = UserAddress::where('user_id','=',$this->uid)->find();
        if(!$userAddress){
            throw new UserException([
                'msg' =>'用户收货地址不存在，下单失败',
                'errorCode' => 60001
            ]);
        }
        //模型查询出来的不是一个数组
        return $userAddress->toArray();
    }

    /**
     * 获取订单的状态
     */
    private function getOrderStatus()
    {
        //访问上面的成员变量
        $status = [
            //status存在的属性
            'pass' => true,
            'orderPrice'  => 0,
            'totalCount' =>0,
            'pStatusArray' => [] //设置空数组，保存的数据是：用来保存订单里面商品的所有详细信息
        ];
        //用循环遍历的方法库存量的对比
        foreach ($this->oProducts as $oProduct)
        {
           $pStatus = $this->getProductStatus(
              $oProduct['product_id'],
              $oProduct['count'],
              $this->products
           );
           if(!$pStatus['haveStock']){
               $status['pass'] = false;
           }
           $status['orderPrice'] += $pStatus['totalPrice'];
            $status['orderCount'] += $pStatus['counts'];
           //把$pStatus push 到pStatusArray里面
            array_push($status['pStatusArray'],$pStatus);
        }
    }

    private function getProductStatus($oPID,$oCount,$products)
    {
        //序号默认为-1
        $pIndex = -1;
        $pStatus = [
            'id' => null,
            'haveStock' => false,
            'counts' =>0,
            'price' => 0,
            'name' =>'',
            'totalPrice' =>0,
            'main_img_url' => null,
        ];
        for ($i=0;$i<count($products);$i++){
           if($oPID == $products[$i]['id']){
               $pIndex = $i;
           }
        }
        if($pIndex==-1){
            //客户端传递的product_id有可能根本不存在
            throw new OrderException([
                'msg' => 'id为'.$oPID.'商品不存在，创建订单失败'
            ]);
        }
        else{
            //具体检测库存量
            $product = $products[$pIndex];
            $pStatus['id'] = $product['id'];
            $pStatus['name'] = $product['name'];
            $pStatus['counts'] = $oCount;
            $pStatus['price'] = $product['price'];
            $pStatus['main_img_url'] = $product['main_img_url'];
            $pStatus['totalPrice'] = $product['price']*$oCount;
            if($product['stock']-$oCount>=0){
                $pStatus['haveStock'] =true;
            }
        }
        return $pStatus;
    }
    //根据订单信息查找真实的商品信息
    private function getProductsByOrder($oProducts)
    {
        //查询数据库
        $oPIDs = [];//商品ig号的数组
        foreach ($oProducts as $item){
            //读取id
            array_push($oPIDs,$item['product_id']);
        }
        //toArray转换成数组
        $products = Product::all([$oPIDs])
        ->visible(['id','price','stock','name','main_img_url'])
        ->toArray();
        return $products;
    }

    /**
     * 微信模板消息
     * @param $orderID
     * @param string $jumpPage
     * @return bool
     * @throws OrderException
     */
    public function delivery($orderID, $jumpPage = '')
    {
        $order = OrderModel::where('id', '=', $orderID)
            ->find();
        if (!$order) {
            throw new OrderException();
        }
        if ($order->status != OrderStatusEnum::PAID) {
            throw new OrderException([
                'msg' => '还没付款呢，想干嘛？或者你已经更新过订单了，不要再刷了',
                'errorCode' => 80002,
                'code' => 403
            ]);
        }
        $order->status = OrderStatusEnum::DELIVERED;
        $order->save();
//            ->update(['status' => OrderStatusEnum::DELIVERED]);
        $message = new DeliveryMessage();
        return $message->sendDeliveryMessage($order, $jumpPage);
    }
}